home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / GNU / patch_2_1.lha / patch-2.1util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-23  |  11.8 KB  |  544 lines

  1. #include "EXTERN.h"
  2. #include "common.h"
  3. #include "INTERN.h"
  4. #include "util.h"
  5. #include "backupfile.h"
  6.  
  7. void my_exit();
  8.  
  9. #ifndef HAVE_STRERROR
  10. static char *
  11. private_strerror (errnum)
  12.      int errnum;
  13. {
  14.   extern char *sys_errlist[];
  15.   extern int sys_nerr;
  16.  
  17.   if (errnum > 0 && errnum <= sys_nerr)
  18.     return sys_errlist[errnum];
  19.   return "Unknown system error";
  20. }
  21. #define strerror private_strerror
  22. #endif /* !HAVE_STRERROR */
  23.  
  24. /* Rename a file, copying it if necessary. */
  25.  
  26. int
  27. move_file(from,to)
  28. char *from, *to;
  29. {
  30.     char bakname[512];
  31.     Reg1 char *s;
  32.     Reg2 int i;
  33.     Reg3 int fromfd;
  34.  
  35.     /* to stdout? */
  36.  
  37.     if (strEQ(to, "-")) {
  38. #ifdef DEBUGGING
  39.     if (debug & 4)
  40.         say2("Moving %s to stdout.\n", from);
  41. #endif
  42.     fromfd = open(from, 0);
  43.     if (fromfd < 0)
  44.         pfatal2("internal error, can't reopen %s", from);
  45.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  46.         if (write(1, buf, i) != 1)
  47.         pfatal1("write failed");
  48.     Close(fromfd);
  49.     return 0;
  50.     }
  51.  
  52.     if (origprae) {
  53.     Strcpy(bakname, origprae);
  54.     Strcat(bakname, to);
  55.     } else {
  56. #ifndef NODIR
  57.     char *backupname = find_backup_file_name(to);
  58.     if (backupname == (char *) 0)
  59.         fatal1("out of memory\n");
  60.     Strcpy(bakname, backupname);
  61.     free(backupname);
  62. #else /* NODIR */
  63.     Strcpy(bakname, to);
  64.         Strcat(bakname, simple_backup_suffix);
  65. #endif /* NODIR */
  66.     }
  67.  
  68.     if (stat(to, &filestat) == 0) {    /* output file exists */
  69. #ifndef AMIGA
  70.     dev_t to_device = filestat.st_dev;
  71.     ino_t to_inode  = filestat.st_ino;
  72.     char *simplename = bakname;
  73.     
  74.     for (s=bakname; *s; s++) {
  75.         if (*s == '/')
  76.         simplename = s+1;
  77.     }
  78. #else /* AMIGA */
  79.     char *simplename = bakname;
  80.  
  81.     for (s=bakname; *s; s++) {
  82.         if (*s == '/' || *s == ':')
  83.         simplename = s+1;
  84.     }
  85. #endif /* AMIGA */
  86.  
  87. #ifndef AMIGA
  88.     /* Find a backup name that is not the same file.
  89.        Change the first lowercase char into uppercase;
  90.        if that isn't sufficient, chop off the first char and try again.  */
  91.     while (stat(bakname, &filestat) == 0 &&
  92.         to_device == filestat.st_dev && to_inode == filestat.st_ino) {
  93.         /* Skip initial non-lowercase chars.  */
  94.         for (s=simplename; *s && !islower(*s); s++) ;
  95.         if (*s)
  96.         *s = toupper(*s);
  97.         else
  98.         Strcpy(simplename, simplename+1);
  99.     }
  100.     while (unlink(bakname) >= 0) ;    /* while() is for benefit of Eunice */
  101. #else /* AMIGA */
  102.         /* The stuff above is not very meaningful on the Amiga */
  103.         Unlink(bakname);
  104. #endif /* AMIGA */
  105.  
  106. #ifdef DEBUGGING
  107.     if (debug & 4)
  108.         say3("Moving %s to %s.\n", to, bakname);
  109. #endif
  110.     if (rename(to, bakname) < 0) {
  111.         say4("Can't backup %s, output is in %s: %s\n", to, from,
  112.          strerror(errno));
  113.         return -1;
  114.     }
  115. #ifndef AMIGA
  116.     while (unlink(to) >= 0) ;
  117. #else /* AMIGA */
  118.         Unlink(to);
  119. #endif /* AMIGA */
  120.     }
  121. #ifdef DEBUGGING
  122.     if (debug & 4)
  123.     say3("Moving %s to %s.\n", from, to);
  124. #endif
  125. #ifndef AMIGA
  126.     if (rename(from, to) < 0) {        /* different file system? */
  127. #else /* AMIGA */
  128.     if (rename(from, to) != 0) {    /* different file system? */
  129. #endif /* AMIGA */
  130.     Reg4 int tofd;
  131.     
  132.     tofd = creat(to, 0666);
  133.     if (tofd < 0) {
  134.         say4("Can't create %s, output is in %s: %s\n",
  135.           to, from, strerror(errno));
  136.         return -1;
  137.     }
  138.     fromfd = open(from, 0);
  139.     if (fromfd < 0)
  140.         pfatal2("internal error, can't reopen %s", from);
  141.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  142.         if (write(tofd, buf, i) != i)
  143.         pfatal1("write failed");
  144.     Close(fromfd);
  145.     Close(tofd);
  146.     }
  147.     Unlink(from);
  148.     return 0;
  149. }
  150.  
  151. /* Copy a file. */
  152.  
  153. void
  154. copy_file(from,to)
  155. char *from, *to;
  156. {
  157.     Reg3 int tofd;
  158.     Reg2 int fromfd;
  159.     Reg1 int i;
  160.     
  161.     tofd = creat(to, 0666);
  162.     if (tofd < 0)
  163.     pfatal2("can't create %s", to);
  164.     fromfd = open(from, 0);
  165.     if (fromfd < 0)
  166.     pfatal2("internal error, can't reopen %s", from);
  167.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  168.     if (write(tofd, buf, i) != i)
  169.         pfatal2("write to %s failed", to);
  170.     Close(fromfd);
  171.     Close(tofd);
  172. }
  173.  
  174. /* Allocate a unique area for a string. */
  175.  
  176. char *
  177. savestr(s)
  178. Reg1 char *s;
  179. {
  180.     Reg3 char *rv;
  181.     Reg2 char *t;
  182.  
  183.     if (!s)
  184.     s = "Oops";
  185.     t = s;
  186.     while (*t++);
  187.     rv = malloc((MEM) (t - s));
  188.     if (rv == Nullch) {
  189.     if (using_plan_a)
  190.         out_of_mem = TRUE;
  191.     else
  192.         fatal1("out of memory\n");
  193.     }
  194.     else {
  195.     t = rv;
  196.     while (*t++ = *s++);
  197.     }
  198.     return rv;
  199. }
  200.  
  201. #if defined(lint) && defined(CANVARARG)
  202.  
  203. /*VARARGS ARGSUSED*/
  204. say(pat) char *pat; { ; }
  205. /*VARARGS ARGSUSED*/
  206. fatal(pat) char *pat; { ; }
  207. /*VARARGS ARGSUSED*/
  208. pfatal(pat) char *pat; { ; }
  209. /*VARARGS ARGSUSED*/
  210. ask(pat) char *pat; { ; }
  211.  
  212. #else
  213.  
  214. /* Vanilla terminal output (buffered). */
  215.  
  216. void
  217. say(pat,arg1,arg2,arg3)
  218. char *pat;
  219. long arg1,arg2,arg3;
  220. {
  221.     fprintf(stderr, pat, arg1, arg2, arg3);
  222.     Fflush(stderr);
  223. }
  224.  
  225. /* Terminal output, pun intended. */
  226.  
  227. void                /* very void */
  228. fatal(pat,arg1,arg2,arg3)
  229. char *pat;
  230. long arg1,arg2,arg3;
  231. {
  232.     fprintf(stderr, "patch: **** ");
  233.     fprintf(stderr, pat, arg1, arg2, arg3);
  234.     my_exit(1);
  235. }
  236.  
  237. /* Say something from patch, something from the system, then silence . . . */
  238.  
  239. void                /* very void */
  240. pfatal(pat,arg1,arg2,arg3)
  241. char *pat;
  242. long arg1,arg2,arg3;
  243. {
  244.     int errnum = errno;
  245.  
  246.     fprintf(stderr, "patch: **** ");
  247.     fprintf(stderr, pat, arg1, arg2, arg3);
  248.     fprintf(stderr, ": %s\n", strerror(errnum));
  249.     my_exit(1);
  250. }
  251.  
  252. #ifndef AMIGA
  253. /* Get a response from the user, somehow or other. */
  254.  
  255. void
  256. ask(pat,arg1,arg2,arg3)
  257. char *pat;
  258. long arg1,arg2,arg3;
  259. {
  260.     int ttyfd;
  261.     int r;
  262.     bool tty2 = isatty(2);
  263.  
  264.     Sprintf(buf, pat, arg1, arg2, arg3);
  265.     Fflush(stderr);
  266.     write(2, buf, strlen(buf));
  267.     if (tty2) {                /* might be redirected to a file */
  268.     r = read(2, buf, sizeof buf);
  269.     }
  270.     else if (isatty(1)) {        /* this may be new file output */
  271.     Fflush(stdout);
  272.     write(1, buf, strlen(buf));
  273.     r = read(1, buf, sizeof buf);
  274.     }
  275.     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
  276.                     /* might be deleted or unwriteable */
  277.     write(ttyfd, buf, strlen(buf));
  278.     r = read(ttyfd, buf, sizeof buf);
  279.     Close(ttyfd);
  280.     }
  281.     else if (isatty(0)) {        /* this is probably patch input */
  282.     Fflush(stdin);
  283.     write(0, buf, strlen(buf));
  284.     r = read(0, buf, sizeof buf);
  285.     }
  286.     else {                /* no terminal at all--default it */
  287.     buf[0] = '\n';
  288.     r = 1;
  289.     }
  290.     if (r <= 0)
  291.     buf[0] = 0;
  292.     else
  293.     buf[r] = '\0';
  294.     if (!tty2)
  295.     say1(buf);
  296. }
  297. #else  /* AMIGA */
  298. /* The closest thing to "/dev/tty" on the Amiga is called "*".
  299.    Open it in any case, because stdin may be redirected, and the
  300.    user can't tell the difference if it's not redirected :-).
  301.    I think this will work with the ARP shell under Kick 1.3 too,
  302.    but I have no way to tell... */
  303.  
  304. void
  305. ask(pat,arg1,arg2,arg3)
  306. char *pat;
  307. long arg1,arg2,arg3;
  308. {
  309.     int console;
  310.     long r;
  311.  
  312.  
  313.     Sprintf (buf, pat, arg1, arg2, arg3);
  314.     console = open ("*", O_RDWR | O_CREAT);
  315.     if (console >= NULL)
  316.       {
  317.         write (console, buf, strlen (buf));
  318.         r = read (console, buf, sizeof (buf));
  319.         Close (console);
  320.       }
  321.     else
  322.       {                /* no terminal at all--default it */
  323.     buf[0] = '\n';
  324.     r = 1;
  325.       }
  326.     if (r <= 0)
  327.         buf[0]=0;
  328.     else
  329.         buf[r]=0;
  330. }
  331. #endif  /* AMIGA */
  332. #endif /* lint */
  333.  
  334. /* How to handle certain events when not in a critical region. */
  335.  
  336. void
  337. set_signals(reset)
  338. int reset;
  339. {
  340. #ifndef lint
  341. #ifndef AMIGA
  342.     static RETSIGTYPE (*hupval)(),(*intval)();
  343. #else /* AMIGA */
  344.     static RETSIGTYPE (*intval)();
  345. #endif /* AMIGA */
  346.  
  347.     if (!reset) {
  348. #ifndef AMIGA
  349.     hupval = signal(SIGHUP, SIG_IGN);
  350.     if (hupval != SIG_IGN)
  351.         hupval = (RETSIGTYPE(*)())my_exit;
  352. #endif /* !AMIGA */
  353.     intval = signal(SIGINT, SIG_IGN);
  354.     if (intval != SIG_IGN)
  355.         intval = (RETSIGTYPE(*)())my_exit;
  356.     }
  357. #ifndef AMIGA
  358.     Signal(SIGHUP, hupval);
  359. #endif /* !AMIGA */
  360.     Signal(SIGINT, intval);
  361. #endif
  362. }
  363.  
  364. /* How to handle certain events when in a critical region. */
  365.  
  366. void
  367. ignore_signals()
  368. {
  369. #ifndef lint
  370. #ifndef AMIGA
  371.     Signal(SIGHUP, SIG_IGN);
  372. #endif /* !AMIGA */
  373.     Signal(SIGINT, SIG_IGN);
  374. #endif
  375. }
  376.  
  377. /* Make sure we'll have the directories to create a file.
  378.    If `striplast' is TRUE, ignore the last element of `filename'.  */
  379.  
  380. void
  381. makedirs(filename,striplast)
  382. Reg1 char *filename;
  383. bool striplast;
  384. {
  385.     char tmpbuf[256];
  386.     Reg2 char *s = tmpbuf;
  387.     char *dirv[20];        /* Point to the NULs between elements.  */
  388.     Reg3 int i;
  389.     Reg4 int dirvp = 0;        /* Number of finished entries in dirv. */
  390.  
  391.     /* Copy `filename' into `tmpbuf' with a NUL instead of a slash
  392.        between the directories.  */
  393.     while (*filename) {
  394.     if (*filename == '/') {
  395.         filename++;
  396.         dirv[dirvp++] = s;
  397.         *s++ = '\0';
  398.     }
  399.     else {
  400.         *s++ = *filename++;
  401.     }
  402.     }
  403.     *s = '\0';
  404.     dirv[dirvp] = s;
  405.     if (striplast)
  406.     dirvp--;
  407.     if (dirvp < 0)
  408.     return;
  409.  
  410. #ifndef AMIGA
  411.     strcpy(buf, "mkdir");
  412. #else /* AMIGA */
  413.     strcpy(buf, "makedir");
  414. #endif /* AMIGA */
  415.     s = buf;
  416.     for (i=0; i<=dirvp; i++) {
  417.     struct stat sbuf;
  418.  
  419.     if (stat(tmpbuf, &sbuf) && errno == ENOENT) {
  420.         while (*s) s++;
  421.         *s++ = ' ';
  422.         strcpy(s, tmpbuf);
  423.     }
  424.     *dirv[i] = '/';
  425.     }
  426.     if (s != buf)
  427.     system(buf);
  428. }
  429.  
  430. /* Make filenames more reasonable. */
  431.  
  432. char *
  433. fetchname(at,strip_leading,assume_exists)
  434. char *at;
  435. int strip_leading;
  436. int assume_exists;
  437. {
  438.     char *fullname;
  439.     char *name;
  440.     Reg1 char *t;
  441. #ifndef AMIGA
  442.     char tmpbuf[200];
  443. #endif /* !AMIGA */
  444.     int sleading = strip_leading;
  445.  
  446.     if (!at)
  447.     return Nullch;
  448.     while (isspace(*at))
  449.     at++;
  450. #ifdef DEBUGGING
  451.     if (debug & 128)
  452.     say4("fetchname %s %d %d\n",at,strip_leading,assume_exists);
  453. #endif
  454. #ifndef AMIGA
  455.     if (strnEQ(at, "/dev/null", 9))    /* so files can be created by diffing */
  456.     return Nullch;            /*   against /dev/null. */
  457. #else /* AMIGA */
  458.     /* This probably doesn't make much sense since you can't diff
  459.        against NIL: on the Amiga... */
  460.     if (strnEQ(at, "NIL:", 9))    /* so files can be created by diffing */
  461.     return Nullch;            /*   against NIL:. */
  462. #endif /* AMIGA */
  463.  
  464.     name = fullname = t = savestr(at);
  465.  
  466. #ifndef AMIGA
  467.     /* Strip off up to `sleading' leading slashes and null terminate.  */
  468.     for (; *t && !isspace(*t); t++)
  469.     if (*t == '/')
  470.         if (--sleading >= 0)
  471.         name = t+1;
  472. #else /* AMIGA */
  473.     /* Strip off up to `sleading' leading slashes or colons and null terminate.  */
  474.     /* Please note that filenames with spaces are not handled correctly due
  475.        to the output format of diff and the assumptions that patch has to
  476.        make because of this output format. */
  477.     for (; *t && !isspace(*t); t++)
  478.     if (*t == '/' || *t == ':')
  479.         if (--sleading >= 0)
  480.         name = t+1;
  481. #endif /* AMIGA */
  482.     *t = '\0';
  483.  
  484.     /* If no -p option was given (957 is the default value!),
  485.        we were given a relative pathname,
  486.        and the leading directories that we just stripped off all exist,
  487.        put them back on.  */
  488. #ifndef AMIGA
  489.     if (strip_leading == 957 && name != fullname && *fullname != '/') {
  490.     name[-1] = '\0';
  491.     if (stat(fullname, &filestat) == 0 && S_ISDIR (filestat.st_mode)) {
  492.         name[-1] = '/';
  493.         name=fullname;
  494.     }
  495.     }
  496. #else /* AMIGA */
  497.     if (strip_leading == 957 && name != fullname && strchr(fullname,':') == NULL) {
  498.     name[-1] = '\0';
  499.     if (stat(fullname, &filestat) == 0 && S_ISDIR (filestat.st_mode)) {
  500.         name[-1] = '/';
  501.         name=fullname;
  502.     }
  503.     }
  504. #endif /* AMIGA */
  505.  
  506.     name = savestr(name);
  507.     free(fullname);
  508.  
  509. #ifndef AMIGA
  510.     if (stat(name, &filestat) && !assume_exists) {
  511.     char *filebase = basename(name);
  512.     int pathlen = filebase - name;
  513.  
  514.     /* Put any leading path into `tmpbuf'.  */
  515.     strncpy(tmpbuf, name, pathlen);
  516.  
  517. #define try(f, a1, a2) (Sprintf(tmpbuf + pathlen, f, a1, a2), stat(tmpbuf, &filestat) == 0)
  518.     if (   try("RCS/%s%s", filebase, RCSSUFFIX)
  519.         || try("RCS/%s"  , filebase,         0)
  520.         || try(    "%s%s", filebase, RCSSUFFIX)
  521.         || try("SCCS/%s%s", SCCSPREFIX, filebase)
  522.         || try(     "%s%s", SCCSPREFIX, filebase))
  523.       return name;
  524.     free(name);
  525.     name = Nullch;
  526.     }
  527. #else /* AMIGA */
  528.     if (stat(name, &filestat) && !assume_exists)
  529.         name = Nullch;
  530. #endif /* AMIGA */
  531.  
  532.     return name;
  533. }
  534.  
  535. char *
  536. xmalloc (size)
  537.      unsigned size;
  538. {
  539.   register char *p = (char *) malloc (size);
  540.   if (!p)
  541.     fatal("out of memory");
  542.   return p;
  543. }
  544.